package org.base.oj.filter;

import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import org.base.oj.common.ErrorCode;
import org.base.oj.common.redis.RedisCache;
import org.base.oj.common.ResultUtils;
import org.base.oj.mapper.UserMapper;
import org.base.oj.domain.LoginUser;
import org.base.oj.utils.JwtUtil;
import org.base.oj.utils.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

@Component
public class TokenFilter extends OncePerRequestFilter {
    @Autowired
    private RedisCache redisCache;

    @Value("${GlobalValue.redisLoginUserKey}")
    String redisLoginUserKey;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader("Authorization");
        String userId;
        //如果没有token需要做的就是放行，后面security的过滤器过不去
        if (token == null){
            filterChain.doFilter(request,response);
            return;
        }
        if(!StringUtils.hasText(token)){
            filterChain.doFilter(request,response);
            return;
        }
        LoginUser loginUser = null;
        //解析token
        try {
            Claims claims = JwtUtil.parseJWT(token);
            userId = claims.getSubject();
            loginUser =  redisCache.getCacheObject(redisLoginUserKey + userId);
        } catch (ExpiredJwtException e) {
            userId = e.getClaims().getSubject();
            loginUser =  redisCache.getCacheObject(redisLoginUserKey + userId);
            //真正的过期---token解析时过期并且redis也过期
           if (loginUser == null) {
               WebUtils.renderString(response, JSON.toJSONString(ResultUtils.error(ErrorCode.AUTH_ERROR,"token过期")));
               return;
           }
        } catch (Exception e) {
            WebUtils.renderString(response, JSON.toJSONString(ResultUtils.error(ErrorCode.AUTH_ERROR,"无效的token")));
            return;
        }
        UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(loginUser,null, loginUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(upat);
        //当token剩余的时间小于等于1个小时的时候,用户发送请求后token时长刷新
        //剩余时长
        long expire = redisCache.getExpire(redisLoginUserKey + userId);
        if (expire > 0 && expire <= 60 * 60 ){
            redisCache.expire(redisLoginUserKey + userId,60 * 60);
        }
        filterChain.doFilter(request,response);
    }
}
